package com.wn.service.controller;

import com.wn.service.confirmhandler.ConfirmHandler;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.lang.Nullable;
import org.springframework.stereotype.Component;

/**
 * @author yellow Docter
 * @date 2022 -08-31
 * @desc direct发送消息
 */
@Component
@Slf4j
public class WorkProductConfirm {

    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Autowired
    private ConfirmHandler confirmHandler;

    public void sendMsg(String exchangeName, String routing, String msg) {

        // ConcurrentSkipListMap   解决并发问题
        //01 发送消息 可以存储卡到  ConcurrentSkipListMap
        //02 如果队列没有收到消息  可以存储到 ConcurrentSkipListMap


        // 消息的生产者，消息发布确认回调函数
        // 参数1：消息数据，包含消息id、消息内容，调用convertAndSend()方法时候可以传入
        // 参数2：是否确认收到消息  (交换机确认)
        // 参数3：消息失败的原因
//        rabbitTemplate.setConfirmCallback(confirmHandler);
        rabbitTemplate.setConfirmCallback((correlationData, ack, cause) -> {

                log.info("消息数据:{}",correlationData);
                log.info("是否确认收到消息:{}",ack);
                log.info("消息失败的原因  :{}",cause);

                if (ack){
                    System.out.println("交换机收到了消息.....");
                }else{
                    System.out.println("=====>交换机收消息失败.....");
                    //出现了问题  重新发送 或者 存储到数据库中，在指定的时间把消息查询出来 进行统一处理
                }

        });

        //判断 交互机中的消息是否到 队列中
        //true 表示消息通过交换机无法路由到队列时候，会把消息返回给生产者
        //false 消息无法路由到队列就直接丢弃

        rabbitTemplate.setMandatory(true);

        // 消息到 队列中的确认机制
        //如果 出现了问题 消息没有到队列中
//        rabbitTemplate.setReturnCallback(confirmHandler);
        rabbitTemplate.setReturnCallback((Message message, int replyCode, String replyText, String exchange, String routingKey)->{

            //消息没有到队列中
            System.out.println("=====>交换机收消息失败.....");
            //出现了问题  重新发送 或者 存储到数据库中，在指定的时间把消息查询出来 进行统一处理

            log.info("消息数据:{}",new String(message.getBody()));
            log.info("应答码:{}",replyCode);
            log.info("字符串 :{}",replyText);
            log.info("交换机,exchange:{}",exchange);
            log.info("路由:{}",routingKey);

        });

        //存储消息
        rabbitTemplate.convertAndSend(exchangeName,routing,msg);
    }

}
